require_relative 'tlv_error'
require_relative '../../util/byte_buffer'

module SmppClient

  module Pdu

    module Tlv

      # Optional Parameters are fields, which may be present in a message. Optional Parameters
      # provide a mechanism for the future introduction of new parameters, as and when defined in
      # future versions of the SMPP protocol.
      #
      # Optional Parameters must always appear at the end of a PDU , in the "Optional Parameters"
      # section of the SMPP PDU. However, they may be included in any convenient order within the
      # "Optional Parameters" section of the SMPP PDU and need not be encoded in the order
      # presented in this document.
      #
      # For a particular SMPP PDU, the ESME or SMSC may include some, all or none of the defined
      # optional parameters as required for the particular application context. For example a paging
      # system may only need to include the “callback number” related optional parameters in a
      # submit_sm operation.

      class Tlv

        include SmppClient::Util

        # TLV mandatory header length in octet bytes.
        HEADER_LENGTH = 4

        attr_reader :tag, :length

        def initialize(arg)
          if arg.kind_of? ByteBuffer
            @tag = arg.remove_short
            @length = arg.remove_short
            if arg.size < @length
              raise TlvError, "#{@tag} TLV value length #{arg.size}, but #{@length} expected."
            end
          else
            @tag = arg
            @length = 0
          end
        end

        def buffer
          val_bytes = value_bytes
          @length = val_bytes.size
          byte_buffer = ByteBuffer.new
          byte_buffer.append_short(@tag)
          byte_buffer.append_short(@length)
          byte_buffer.append_bytes(val_bytes)
        end

        def to_s
          "tag: #{@tag}, length: #{@length}"
        end

        protected

        def value_bytes
          []
        end

      end

    end

  end

end